package com.snailct.bpp.router.datachange;



import com.snailct.bpp.commons.utils.ReflectUtil;
import com.snailct.bpp.router.util.XMLUtil;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.xpath.XPath;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

/**
 * Created by huangxa on 2016/6/17.
 */
public class XMLMessageOperation {
    private String refId;
    private String taskId;
    private String xmlStr;
    public String getTaskId() {
        return taskId;
    }

    public void setTaskId(String taskId) {
        this.taskId = taskId;
    }

    public String getRefId() {
        return refId;
    }

    public void setRefId(String refId) {
        this.refId = refId;
    }

    public void parseXMLToDB() throws JDOMException {
        String sql = "select * from SOA_SYS_ACCEPT_MESSAGE WHERE auto_id="+refId;
        ResultSet rs = DaoOperation.executeQuery(sql);
        try {
            if(rs.next()){
                String xmlStr = rs.getString("xmlstr");
                Document doc = XMLUtil.stringToXMl(xmlStr);
                Element rootElement = doc.getRootElement();
                String business = rootElement.getChildText("business");
                String destSystem = rootElement.getChildText("destSystem");
                String sql1 = "update SOA_SYS_ACCEPT_MESSAGE SET business='"+business+"',destSystem='"+destSystem+"' where auto_id="+refId;
                DaoOperation.execute(sql1);
                //根据业务类型找到结构描述文件进行解析，如果目的地不为SOAPlatform则写入一条新的任务
                MessageOperation messageOperation = new MessageOperation();
                messageOperation.setInXmlDescFileName(business+".xml");
                messageOperation.genInMessageNodeArray();
                List<MessageNode> messageNodeArray = messageOperation.getMessageNodeArray();

                //得到非叶子节点
                MessageNodeOpertaion messageNodeOP = new MessageNodeOpertaion();
                messageNodeOP.setNodeArray(messageNodeArray);
                List<MessageNode> parentNodeArray = messageNodeOP.findParentNodeArray();
                //遍历非叶子节点结构表示数据，据此填充数据
                for(int i=0;i<parentNodeArray.size();i++){
                    MessageNode currentNode = parentNodeArray.get(i);
                    List<MessageNode> sonNodeArray = messageNodeOP.findSonNodeArray(currentNode);
                    int fieldCount = sonNodeArray.size();
                    int level = Integer.parseInt(currentNode.getCurrentElementLevel());
                    if(level>1){
                        fieldCount++;
                    }
                    //声明字段名和字段值数组
                    String fieldNameStrArray[] = new String[fieldCount];
                    String fieldValueStrArray[] = new String[fieldCount];
                    for(int j=0;j<sonNodeArray.size();j++){
                        MessageNode sonNode = sonNodeArray.get(j);
                        String xpath = "//"+sonNode.getParentElementName()+"/"+sonNode.getCurrentElementName();
                        Element element = (Element) XPath.selectSingleNode(rootElement,xpath);
                        fieldValueStrArray[j]=element.getText();
                        fieldNameStrArray[j]=sonNode.getCurrentElementName();
                    }
                    //如果有外键（即父节点有主键），也就是说非叶子节点报文深度大于1
                    if(level>1){
                        //遍历找到父节点，然后得到主键名和主键值
                        boolean istrue=false;
                        for(int j=0;j<parentNodeArray.size();j++){
                            MessageNode tempNode = parentNodeArray.get(j);
                            String priKey = tempNode.getCurrentElementPrimaryKey();
                            if(priKey!=null&&priKey.length()!=0&&currentNode.getParentElementName().equals(tempNode.getCurrentElementName())){
                                fieldNameStrArray[fieldCount-1]=priKey;
                                String xpath = "//"+tempNode.getCurrentElementName()+"/"+priKey;
                                Element element = (Element)XPath.selectSingleNode(rootElement,xpath);
                                fieldValueStrArray[fieldCount-1]=element.getText();
                                istrue=true;
                            }
                        }
                        if(!istrue) fieldCount--;
                    }
                    if(fieldCount==0) continue;
                    //往数据库表中填充数据，先查是否已有数据
                    String sql3="select * from SOA_AUTO_"+business+"_"+currentNode.getCurrentElementName()+" where ";
                    for(int j=0;j<fieldCount;j++){
                        if(j==fieldNameStrArray.length-1){
                            sql3+=fieldNameStrArray[j]+"='"+fieldValueStrArray[j]+"'";
                        }else{
                            sql3+=fieldNameStrArray[j]+"='"+fieldValueStrArray[j]+"' and ";
                        }
                    }
                    ResultSet rs1 = DaoOperation.executeQuery(sql3);
                    if(!rs1.next()){
                        sql3="insert into SOA_AUTO_"+business+"_"+currentNode.getCurrentElementName()+"(";
                        for(int j=0;j<fieldCount;j++){
                            if(j==fieldNameStrArray.length-1){
                                sql3+=fieldNameStrArray[j];
                            }else{
                                sql3+=fieldNameStrArray[j]+",";
                            }
                        }
                        sql3+=") values(";
                        for(int j=0;j<fieldCount;j++){
                            if(j==fieldValueStrArray.length-1){
                                sql3+="'"+fieldValueStrArray[j]+"'";
                            }else{
                                sql3+="'"+fieldValueStrArray[j]+"',";
                            }
                        }
                        sql3+=")";
                        DaoOperation.execute(sql3);
                    }


                }
                TaskOperation.taskFinish(taskId);

            }
        } catch (SQLException e) {
            e.printStackTrace();
        }

    }
    //转发报文
    public void sendMessage(){
        String sql = "select * from SOA_SYS_ACCEPT_MESSAGE where auto_id="+refId;
        ResultSet rs = DaoOperation.executeQuery(sql);
        try{
            if(rs.next()){
                xmlStr = rs.getString("xmlStr");
                String xmlStren=rs.getString("xmlstr");
                Document doc = XMLUtil.stringToXMl(xmlStr);
                Element rootElement = doc.getRootElement();
                String business = rootElement.getChildText("business");
                String destSystem = rootElement.getChildText("destSystem");
                String webServiceUrl = null;
                String serviceMethod=null;
                int interfaceType=0;
                String componentName = null;
                String args = null;

                sql = "select * from soa_sys_exchangesystem where destSystem='"+destSystem+"'";
                ResultSet rsdc = DaoOperation.executeQuery(sql);
                if(rsdc.next()){
                    webServiceUrl = rsdc.getString("WSURL");
                    serviceMethod = rsdc.getString("METHODNAME");
                    interfaceType = rsdc.getInt("INTERFACETYPE");
                    componentName = rsdc.getString("componentName");
                    args = rsdc.getString("argsType");
                }
                //webservice 方式转发
                if(interfaceType==1){
                    CallAWebService call = new CallAWebService();
                    call.setMethodName(serviceMethod);
                    call.setSendStr(xmlStren);
                    call.setWebServiceUrl(webServiceUrl);
                    call.sendMessage();
                    call.getSendResult();
                    String updateResult = "update SOA_SYS_ACCEPT_MESSAGE set sendResult='"+call.getSendResult()+"' where auto_id="+refId;
                    DaoOperation.execute(updateResult);
                    TaskOperation.taskFinish(taskId);
                }else if(interfaceType==2){//spring调用
                    /*System.out.println("调用spring服务，服务为:");
                    Contribution baseContribution = new Contribution("component-base","bpp-impl/contribution/component-base.jar");
                    Node node = NodeFactory.newInstance().createNode(baseContribution);
                    node.start();
                    Class<?> clazz = Class.forName(webServiceUrl);
                    node.getService(clazz,componentName);
                    Object[] params = getInvokeArgs(xmlStren,args);
                    ReflectUtil.invoke(node.getService(clazz,serviceMethod),serviceMethod,params);
                    node.stop();*/
                }
            }
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    private Object[] getInvokeArgs(String reqXml,String arg) throws JDOMException, ClassNotFoundException, IllegalAccessException, InstantiationException {
        List<Object> rtnObjs = new ArrayList<Object>();
        //参数类型
        String[] argClasses = arg.split(";");
        //根据XML文件
        Document doc = XMLUtil.stringToXMl(xmlStr);
        Element rootElement = doc.getRootElement();
        String business = rootElement.getChildText("business");
        MessageOperation messageOperation = new MessageOperation();
        messageOperation.setInXmlDescFileName(business+".xml");
        messageOperation.genInMessageNodeArray();
        List<MessageNode> messageNodeArray = messageOperation.getMessageNodeArray();

        //得到非叶子节点
        MessageNodeOpertaion messageNodeOP = new MessageNodeOpertaion();
        messageNodeOP.setNodeArray(messageNodeArray);
        List<MessageNode> parentNodeArray = messageNodeOP.findParentNodeArray();
        //遍历非叶子节点结构表示数据，据此填充数据
        for(int i=0;i<parentNodeArray.size();i++){
            MessageNode currentNode = parentNodeArray.get(i);
            boolean isMatchArgType = false;
            String matchAryType = null;
            for(String argType : argClasses){
                if(currentNode.getCurrentElementName().equals(argType.substring(argType.lastIndexOf('.')+1))){
                    isMatchArgType = true;
                    matchAryType = argType;
                }
            }
            if(!isMatchArgType){
                throw new RuntimeException("没有配置的参数类型");
            }
            List<MessageNode> sonNodeArray = messageNodeOP.findSonNodeArray(currentNode);
            int fieldCount = sonNodeArray.size();
            int level = Integer.parseInt(currentNode.getCurrentElementLevel());
            if(level>1){
                fieldCount++;
            }
            //声明字段名和字段值数组
            String fieldNameStrArray[] = new String[fieldCount];
            String fieldValueStrArray[] = new String[fieldCount];
            Object argObjs = Class.forName(matchAryType).newInstance();
            for(int j=0;j<sonNodeArray.size();j++){
                MessageNode sonNode = sonNodeArray.get(j);
                String xpath = "//"+sonNode.getParentElementName()+"/"+sonNode.getCurrentElementName();
                Element element = (Element) XPath.selectSingleNode(rootElement,xpath);
                fieldValueStrArray[j]=element.getText();
                fieldNameStrArray[j]=sonNode.getCurrentElementName();
                ReflectUtil.setMethodValue(argObjs,sonNode.getCurrentElementName(),element.getText());
                rtnObjs.add(argObjs);
            }
            //如果有外键（即父节点有主键），也就是说非叶子节点报文深度大于1
            if(level>1){
                //遍历找到父节点，然后得到主键名和主键值
                boolean istrue=false;
                for(int j=0;j<parentNodeArray.size();j++){
                    MessageNode tempNode = parentNodeArray.get(j);
                    String priKey = tempNode.getCurrentElementPrimaryKey();
                    if(priKey!=null&&priKey.length()!=0&&currentNode.getParentElementName().equals(tempNode.getCurrentElementName())){
                        fieldNameStrArray[fieldCount-1]=priKey;
                        String xpath = "//"+tempNode.getCurrentElementName()+"/"+priKey;
                        Element element = (Element)XPath.selectSingleNode(rootElement,xpath);
                        fieldValueStrArray[fieldCount-1]=element.getText();
                        istrue=true;
                    }
                }
                if(!istrue) fieldCount--;
            }
            if(fieldCount==0) continue;


        }
        return rtnObjs.toArray();
    }
}
